import moment from 'moment'

const HHmm = 'HHmm'
const HHmmss = 'HHmmss'
const yyyyMMdd = 'YYYYMMDD'
const yyyyMMddHHmmss = 'YYYYMMDDHHmmss'
const yyyyMMddHHmmssSSS = 'YYYYMMDDHHmmssSSS'

const HH_mm = 'HH:mm'
const HH_mm_ss = 'HH:mm:ss'
const yyyy_MM_dd = 'YYYY-MM-DD'
const yyyy_MM_dd_HH_mm_ss = 'YYYY-MM-DD HH:mm:ss'
const yyyy_MM_dd_HH_mm_ss_SSS = 'YYYY-MM-DD HH:mm:ss.SSS'

const zh_HH_mm = 'HH时mm分'
const zh_HH_mm_ss = 'HH时mm分ss秒'
const zh_yyyy_MM_dd = 'YYYY年MM月DD日'
const zh_yyyy_MM_dd_HH_mm_ss = 'YYYY年MM月DD日 HH时mm分ss秒'
const zh_yyyy_MM_dd_HH_mm_ss_SSS = 'YYYY年MM月DD日 HH时mm分ss秒SSS毫秒'

// export const Week = {
// Mon("星期一", "Monday"),
// Tue("星期二", "Tuesday"),
// Wed("星期三", "Wednesday"),
// Thu("星期四", "Thursday"),
// Fri("星期五", "Friday"),
// Sat("星期六", "Saturday"),
// Sun("星期日", "Sunday"),
// }

/**
 * 日期操作，包装 moment ，让日期格式跟其他系统保持一致
 * 格式映射关系
 * 年:YYYY:yyyy
 * 月:MM:MM
 * 日:DD:dd
 * 时:hh:HH
 * 分:mm:mm
 * 秒:ss:ss
 * 毫秒:SSS:SSS
 */
export default class Dates {

  /**
   * moment.Moment 对象构造
   * @param momentDate {moment.Moment}
   */
  constructor(momentDate) {
    /**
     * @type {moment.Moment}
     */
    this.momentDate = momentDate
  }

  static demo() {
    if (process.env.NODE_ENV === 'development') {
      console.log(['Date parse', 'Dates.date(new Date())', Dates.date(new Date()).format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['yyyy-MM parse', 'Dates.parse(\'2021-01\', \'yyyy-MM\')', Dates.parse('2021-01', 'yyyy-MM').format_yyyy_MM_dd_HH_mm_ss_SSS()])

      console.log(['HHmm parse', 'Dates.HHmmss(\'1001\')', Dates.HHmm('1001').format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['HH:mm parse', 'Dates.HHmmss(\'10:01\')', Dates.HH_mm('10:01').format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['HHmmss parse', 'Dates.HHmmss(\'220203\')', Dates.HHmmss('220203').format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['HH:mm:ss parse', 'Dates.HH_mm_ss(\'22:02:03\')', Dates.HH_mm_ss('22:02:03').format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['yyyyMMdd parse', 'Dates.yyyyMMdd(\'20210101\')', Dates.yyyyMMdd('20210101').format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['yyyy-MM-dd parse', 'Dates.yyyy_MM_dd(\'2021-01-01\')', Dates.yyyy_MM_dd('2021-01-01').format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['yyyyMMddHHmmss parse', 'Dates.yyyyMMddHHmmss(\'20210101220203\')', Dates.yyyyMMddHHmmss('20210101220203').format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['yyyy-MM-dd HH:mm:ss parse', 'Dates.yyyy_MM_dd_HH_mm_ss(\'2021-01-01 22:02:03\')', Dates.yyyy_MM_dd_HH_mm_ss('2021-01-01 22:02:03').format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['yyyyMMddHHmmssSSS parse', 'Dates.yyyyMMddHHmmssSSS(\'20210101220203123\')', Dates.yyyyMMddHHmmssSSS('20210101220203123').format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['yyyy-MM-dd HH:mm:ss.SSS parse', 'Dates.yyyy_MM_dd_HH_mm_ss_SSS(\'2021-01-01 22:02:03.123\')', Dates.yyyy_MM_dd_HH_mm_ss_SSS('2021-01-01 22:02:03.123').format_yyyy_MM_dd_HH_mm_ss_SSS()])

      console.log(['HHmm', 'Dates.now().format_HHmmss()', Dates.now().format_HHmm()])
      console.log(['HH:mm', 'Dates.now().format_HHmmss()', Dates.now().format_HH_mm()])
      console.log(['HHmmss', 'Dates.now().format_HHmmss()', Dates.now().format_HHmmss()])
      console.log(['HH:mm:ss', 'Dates.now().format_HH_mm_ss()', Dates.now().format_HH_mm_ss()])
      console.log(['yyyyMMdd', 'Dates.now().format_yyyyMMdd()', Dates.now().format_yyyyMMdd()])
      console.log(['yyyy-MM-dd', 'Dates.now().format_yyyy_MM_dd()', Dates.now().format_yyyy_MM_dd()])
      console.log(['yyyyMMddHHmmss', 'Dates.now().format_yyyyMMddHHmmss()', Dates.now().format_yyyyMMddHHmmss()])
      console.log(['yyyy-MM-dd HH:mm:ss', 'Dates.now().format_yyyy_MM_dd_HH_mm_ss()', Dates.now().format_yyyy_MM_dd_HH_mm_ss()])
      console.log(['yyyyMMddHHmmssSSS', 'Dates.now().format_yyyyMMddHHmmssSSS()', Dates.now().format_yyyyMMddHHmmssSSS()])
      console.log(['yyyy-MM-dd HH:mm:ss.SSS', 'Dates.now().format_yyyy_MM_dd_HH_mm_ss_SSS()', Dates.now().format_yyyy_MM_dd_HH_mm_ss_SSS()])
      console.log(['HH时mm分', 'Dates.now().format_zh_HH_mm()', Dates.now().format_zh_HH_mm()])
      console.log(['HH时mm分ss秒', 'Dates.now().format_zh_HH_mm_ss()', Dates.now().format_zh_HH_mm_ss()])
      console.log(['yyyy年MM月dd日', 'Dates.now().format_zh_yyyy_MM_dd()', Dates.now().format_zh_yyyy_MM_dd()])
      console.log(['yyyy年MM月dd日 HH时mm分ss秒', 'Dates.now().format_zh_yyyy_MM_dd_HH_mm_ss()', Dates.now().format_zh_yyyy_MM_dd_HH_mm_ss()])
      console.log(['yyyy年MM月dd日 HH时mm分ss秒SSS毫秒', 'Dates.now().format_zh_yyyy_MM_dd_HH_mm_ss_SSS()', Dates.now().format_zh_yyyy_MM_dd_HH_mm_ss_SSS()])

      console.log(['yyyy年MM月', 'Dates.now().format(\'yyyy年MM月\')', Dates.now().format('yyyy年MM月')])
    }
  }

  /**
   * 当前时间
   * @return {Dates}
   */
  static now() {
    return new Dates(moment())
  }

  /**
   * Date 对象转 Dates
   * @param date {Date}
   * @return {Dates}
   */
  static date(date) {
    return new Dates(moment(date))
  }

  /**
   * 使用 moment 自动识别 value 转 Dates
   * @param value {string}
   * @param pattern {string} 日期格式
   * @return {Dates}
   */
  static parse(value, pattern) {
    if (pattern) {
      // 处理 moment 与常规格式不一样的地方， https://momentjs.com/docs/#/parsing
      pattern = pattern.replace('yyyy', 'YYYY').replace('dd', 'DD')
      return new Dates(moment(value, pattern))
    }
    return new Dates(moment(value))
  }

  /**
   * HHmm 字符串日期转 Dates 对象
   * @param value {string}
   * @return {Dates}
   */
  static HHmm(value) {
    return new Dates(moment(value, HHmm))
  }

  /**
   * HHmmss 字符串日期转 Dates 对象
   * @param value {string}
   * @return {Dates}
   */
  static HHmmss(value) {
    return new Dates(moment(value, HHmmss))
  }

  /**
   * yyyyMMdd 字符串日期转 Dates 对象
   * @param value {string}
   * @return {Dates}
   */
  static yyyyMMdd(value) {
    return new Dates(moment(value, yyyyMMdd))
  }

  /**
   * yyyyMMddHHmmss 字符串日期转 Dates 对象
   * @param value {string}
   * @return {Dates}
   */
  static yyyyMMddHHmmss(value) {
    return new Dates(moment(value, yyyyMMddHHmmss))
  }

  /**
   * yyyyMMddHHmmssSSS 字符串日期转 Dates 对象
   * @param value {string}
   * @return {Dates}
   */
  static yyyyMMddHHmmssSSS(value) {
    return new Dates(moment(value, yyyyMMddHHmmssSSS))
  }

  /**
   * HH_mm 字符串日期转 Dates 对象
   * @param value {string}
   * @return {Dates}
   */
  static HH_mm(value) {
    return new Dates(moment(value, HH_mm))
  }

  /**
   * HH_mm_ss 字符串日期转 Dates 对象
   * @param value {string}
   * @return {Dates}
   */
  static HH_mm_ss(value) {
    return new Dates(moment(value, HH_mm_ss))
  }

  /**
   * yyyy_MM_dd 字符串日期转 Dates 对象
   * @param value {string}
   * @return {Dates}
   */
  static yyyy_MM_dd(value) {
    return new Dates(moment(value, yyyy_MM_dd))
  }

  /**
   * yyyy_MM_dd_HH_mm_ss 字符串日期转 Dates 对象
   * @param value {string}
   * @return {Dates}
   */
  static yyyy_MM_dd_HH_mm_ss(value) {
    return new Dates(moment(value, yyyy_MM_dd_HH_mm_ss))
  }

  /**
   * yyyy_MM_dd_HH_mm_ss_SSS 字符串日期转 Dates 对象
   * @param value {string}
   * @return {Dates}
   */
  static yyyy_MM_dd_HH_mm_ss_SSS(value) {
    return new Dates(moment(value, yyyy_MM_dd_HH_mm_ss_SSS))
  }

  /**
   * moment 对象转换为 yyyyMMdd 格式字符串
   * @param pattern {string} 日期格式
   * @return {string}
   */
  format(pattern) {
    if (pattern) {
      // 处理 moment 与常规格式不一样的地方， https://momentjs.com/docs/#/parsing
      pattern = pattern.replace('yyyy', 'YYYY').replace('dd', 'DD')
    }
    return this.momentDate.format(pattern)
  }

  /**
   * moment 对象转换为 HHmm 格式字符串
   * @return {string}
   */
  format_HHmm() {
    return this.momentDate.format(HHmm)
  }

  /**
   * moment 对象转换为 HHmmss 格式字符串
   * @return {string}
   */
  format_HHmmss() {
    return this.momentDate.format(HHmmss)
  }

  /**
   * moment 对象转换为 yyyyMMdd 格式字符串
   * @return {string}
   */
  format_yyyyMMdd() {
    return this.momentDate.format(yyyyMMdd)
  }

  /**
   * moment 对象转换为 yyyyMMddHHmmss 格式字符串
   * @return {string}
   */
  format_yyyyMMddHHmmss() {
    return this.momentDate.format(yyyyMMddHHmmss)
  }

  /**
   * moment 对象转换为 yyyyMMddHHmmssSSS 格式字符串
   * @return {string}
   */
  format_yyyyMMddHHmmssSSS() {
    return this.momentDate.format(yyyyMMddHHmmssSSS)
  }

  /**
   * moment 对象转换为 HH:mm 格式字符串
   * @return {string}
   */
  format_HH_mm() {
    return this.momentDate.format(HH_mm)
  }

  /**
   * moment 对象转换为 HH:mm:ss 格式字符串
   * @return {string}
   */
  format_HH_mm_ss() {
    return this.momentDate.format(HH_mm_ss)
  }

  /**
   * moment 对象转换为 yyyy-MM-dd 格式字符串
   * @return {string}
   */
  format_yyyy_MM_dd() {
    return this.momentDate.format(yyyy_MM_dd)
  }

  /**
   * moment 对象转换为 yyyy-MM-dd hh:mm:ss 格式字符串
   * @return {string}
   */
  format_yyyy_MM_dd_HH_mm_ss() {
    return this.momentDate.format(yyyy_MM_dd_HH_mm_ss)
  }

  /**
   * moment 对象转换为 yyyy-MM-dd hh:mm:ss.SSS 格式字符串
   * @return {string}
   */
  format_yyyy_MM_dd_HH_mm_ss_SSS() {
    return this.momentDate.format(yyyy_MM_dd_HH_mm_ss_SSS)
  }

  /**
   * moment 对象转换为 yyyy-MM-dd 格式字符串
   * @return {string}
   */
  format_zh_yyyy_MM_dd() {
    return this.momentDate.format(zh_yyyy_MM_dd)
  }

  /**
   * moment 对象转换为 HH时mm分 格式字符串
   * @return {string}
   */
  format_zh_HH_mm() {
    return this.momentDate.format(zh_HH_mm)
  }

  /**
   * moment 对象转换为 HH时mm分ss 格式字符串
   * @return {string}
   */
  format_zh_HH_mm_ss() {
    return this.momentDate.format(zh_HH_mm_ss)
  }

  /**
   * moment 对象转换为 yyyy年MM月dd日 hh时mm分ss秒 格式字符串
   * @return {string}
   */
  format_zh_yyyy_MM_dd_HH_mm_ss() {
    return this.momentDate.format(zh_yyyy_MM_dd_HH_mm_ss)
  }

  /**
   * moment 对象转换为 yyyy年MM月dd日 hh时mm分ss秒SSS毫秒 格式字符串
   * @return {string}
   */
  format_zh_yyyy_MM_dd_HH_mm_ss_SSS() {
    return this.momentDate.format(zh_yyyy_MM_dd_HH_mm_ss_SSS)
  }

  /**
   * 转换为毫秒数： ms
   *
   * @return {number}
   */
  toTimeMillis() {
    return this.momentDate.date()
  }

  /**
   * 转换为秒数： s
   *
   * @return {number}
   */
  toTimeSecond() {
    return this.momentDate.date() / 1000
  }

  /**
   * 获取：年
   *
   * @return {number}
   */
  year() {
    return this.momentDate.year()
  }

  /**
   * 获取：月
   *
   * @return {number}
   */
  month() {
    return this.momentDate.month()
  }

  /**
   * 获取：日
   *
   * @return {number}
   */
  day() {
    return this.momentDate.day()
  }

  // /**
  //  * 获取：星期
  //  *
  //  * @return {@link Week}
  //  */
  // public Week week() {
  //   return this.momentDate.week()
  // }

  /**
   * 获取：时
   *
   * @return {number}
   */
  hour() {
    return this.momentDate.hour()
  }

  /**
   * 获取：分
   *
   * @return {number}
   */
  minute() {
    return this.momentDate.minute()
  }

  /**
   * 获取：秒
   *
   * @return {number}
   */
  second() {
    return this.momentDate.second()
  }

  /**
   * 年【增加|减少】
   *
   * @param value {number} 正数为增加，负数表示减少
   * @return {Dates}
   */
  addYear(value) {
    // years	y
    // quarters	Q
    // months	M
    // weeks	w
    // days	d
    // hours	h
    // minutes	m
    // seconds	s
    // milliseconds	ms
    if (value) {
      if (value > 0) {
        this.momentDate.add(value, 'y')
      } else if (value < 0) {
        this.momentDate.subtract(Math.abs(value), 'y')
      }
    }
    return this
  }

  /**
   *月【增加|减少】
   *
   * @param value {number} 正数为增加，负数表示减少
   * @return {Dates}
   */
  addMonth(value) {
    if (value) {
      if (value > 0) {
        this.momentDate.add(value, 'M')
      } else if (value < 0) {
        this.momentDate.subtract(Math.abs(value), 'M')
      }
    }
    return this
  }

  /**
   *日【增加|减少】
   *
   * @param value {number} 正数为增加，负数表示减少
   * @return {Dates}
   */
  addDay(value) {
    if (value) {
      if (value > 0) {
        this.momentDate.add(value, 'd')
      } else if (value < 0) {
        this.momentDate.subtract(Math.abs(value), 'd')
      }
    }
    return this
  }

  /**
   *星期【增加|减少】
   *
   * @param value {number} 正数为增加，负数表示减少
   * @return {Dates}
   */
  addWeek(value) {
    if (value) {
      if (value > 0) {
        this.momentDate.add(value, 'w')
      } else if (value < 0) {
        this.momentDate.subtract(Math.abs(value), 'w')
      }
    }
    return this
  }

  /**
   *时【增加|减少】
   *
   * @param value {number} 正数为增加，负数表示减少
   * @return {Dates}
   */
  addHour(value) {
    if (value) {
      if (value > 0) {
        this.momentDate.add(value, 'h')
      } else if (value < 0) {
        this.momentDate.subtract(Math.abs(value), 'h')
      }
    }
    return this
  }

  /**
   *分【增加|减少】
   *
   * @param value {number} 正数为增加，负数表示减少
   * @return {Dates}
   */
  addMinute(value) {
    if (value) {
      if (value > 0) {
        this.momentDate.add(value, 'm')
      } else if (value < 0) {
        this.momentDate.subtract(Math.abs(value), 'm')
      }
    }
    return this
  }

  /**
   *秒【增加|减少】
   *
   * @param value {number} 正数为增加，负数表示减少
   * @return {Dates}
   */
  addSecond(value) {
    if (value) {
      if (value > 0) {
        this.momentDate.add(value, 's')
      } else if (value < 0) {
        this.momentDate.subtract(Math.abs(value), 's')
      }
    }
    return this
  }

  /**
   * 计算并设置为上周一的日期
   *
   * @return {Dates}
   */
  prevMonday() {
    this.momentDate.subtract(1, 'w') // 设置为上周
    this.momentDate.week(1) // 设置为周一
    return this
  }

  /**
   * 计算并设置为下周一的日期
   *
   * @return {Dates}
   */
  nextMonday() {
    this.momentDate.add(1, 'w') // 设置为下周
    this.momentDate.week(1) // 设置为周一
    return this
  }

  /**
   * 当天的开始时间
   * 设置为当天 0 时 0 分 0 秒 0 毫秒
   * @return {Dates}
   */
  beginTimeOfDay() {
    this.hour(0).minute(0).second(0).ms(0)
    return this
  }

  /**
   * 当前小时时间
   * 设置为当前小时 x 时 0 分 0 秒 0 纳秒
   * @return {Dates}
   */
  beginTimeOfMinute() {
    this.m(0).s(0).ns(0)
    return this
  }

  /**
   * 设置为当月第一天
   * @return {Dates}
   */
  firstDayOfMonth() {
    this.momentDate.startOf('M')
    return this
  }

  /**
   * 设置为下个月1号
   * @return {Dates}
   */
  firstDayOfNextMonth() {
    this.addMonth(1)
    this.momentDate.startOf('M')
    return this
  }

  /**
   * 设置为当月最后一天
   * @return {Dates}
   */
  lastDayOfMonth() {
    this.momentDate.endOf('M')
    return this
  }

  /**
   * 设置为上月最后一天
   * @return {Dates}
   */
  lastDayOfPrevMonth() {
    this.addMonth(-1)
    this.momentDate.endOf('M')
    return this
  }

//
// /**
//  * 比对两个日期
//  * <pre>
//  *     小于 destDate 返回 -1；左小，右大；2018-01-01 | 2018-01-02=-1
//  *     大于 destDate 返回 1； 左大，右小；2018-01-02 | 2018-01-01= 1
//  *     相等返回 0
//  *
//  * @param destDate Dates
//  * @return int
//  */
// public int compare(Dates destDate) {
//   final long value = this.toTimeMillis() - destDate.toTimeMillis();
//   if (value < 0) {
//     return -1;
//   }
//   if (value > 0) {
//     return 1;
//   }
//   return 0;
// }
//
// /**
//  * 比对两个日期，左边 > 右边
//  *
//  * @param destDate Dates
//  * @return boolean
//  */
// public boolean gt(Dates destDate) {
//   return 1 == compare(destDate);
// }
//
// /**
//  * 比对两个日期，左边 < 右边
//  *
//  * @param destDate Dates
//  * @return boolean
//  */
// public boolean lt(Dates destDate) {
//   return -1 == compare(destDate);
// }
//
// /**
//  * 比对两个日期，左边 >= 右边
//  *
//  * @param destDate Dates
//  * @return boolean
//  */
// public boolean ge(Dates destDate) {
//   return -1 != compare(destDate);
// }
//
// /**
//  * 比对两个日期，左边 <= 右边
//  *
//  * @param destDate Dates
//  * @return boolean
//  */
// public boolean le(Dates destDate) {
//   return 1 != compare(destDate);
// }
//
// /**
//  * 比对两个日期，左边 == 右边
//  *
//  * @param destDate Dates
//  * @return boolean
//  */
// public boolean eq(Dates destDate) {
//   return 0 == compare(destDate);
// }
//
// /**
//  * 获取时间间隔
//  *
//  * @return {@link Duration}
//  */
// public Duration getTimeConsuming() {
// // import java.time.Duration;
// // import java.time.Period;
//   return Duration.between(value, LocalDateTime.now());
// }
//
// /**
//  * 获取时间间隔，m分s秒
//  *
//  * @return String
//  */
// public String getTimeConsumingText() {
//   final Duration duration = getTimeConsuming();
//   return (Math.abs(duration.toHours()) > 0 ? String.format("%d时", duration.toHours()) : "")
//     .concat(Math.abs(duration.toMinutes()) > 0 ? String.format("%d分", duration.toMinutes() % 60) : "")
//     .concat(String.format("%d秒", (duration.toMillis() / 1000) % 60));
// }
//
// /**
//  * 绝对值：获取两个日期之间相差的天数
//  * abs(目标日期destDate - 当前dates)
//  *
//  * @param destDate Dates 目标日期
//  * @return int 相差天数
//  */
// public int getDifferDay(Dates destDate) {
//   return Math.abs((int) Duration.between(value, destDate.get()).toDays());
// }
//
// /**
//  * 获取本年按季度划分的时间区间集合
//  * 数据示例：[{"begin":"2017-01-01 00:00:00","end":"2017-03-31 23:59:59"}, {"begin":"2017-04-01 00:00:00","end":"2017-06-30 23:59:59"}, {"begin":"2017-07-01 00:00:00","end":"2017-09-30 23:59:59"}, {"begin":"2017-10-01 00:00:00","end":"2017-12-31 23:59:59"}]
//  *
//  * @return {@link List}{@link List<Range>}
//  */
// public List<Range> getRangeOfQuarter() {
//   return Stream.of(
//     new int[]{1, 3},
//   new int[]{4, 6},
//   new int[]{7, 9},
//   new int[]{10, 12}
// )
// .map(arr -> Range.builder()
//     .begin(month(arr[0]).firstDayOfMonth().beginTimeOfDay().timestamp())
//     .end(month(arr[1]).lastDayOfMonth().endTimeOfDay().timestamp())
//     .build()
//   )
//     .collect(Collectors.toList());
// }
//
// /**
//  * 获取当月时间区间
//  * 数据示例：{"begin":"2017-01-01 00:00:00","end":"2017-1-31 23:59:59"}
//  *
//  * @return {@link Range}
//  */
// public Range getRangeOfMonth() {
//   return Range.builder()
//     .begin(firstDayOfMonth().beginTimeOfDay().timestamp())
//     .end(lastDayOfMonth().endTimeOfDay().timestamp())
//     .build();
// }
//
// /**
//  * 获取当年时间区间
//  * 数据示例：{"begin":"2017-01-01 00:00:00","end":"2017-12-31 23:59:59"}
//  *
//  * @return {@link Range}
//  */
// public Range getRangeOfYear() {
//   return Range.builder()
//     .begin(month(1).firstDayOfMonth().beginTimeOfDay().timestamp())
//     .end(month(12).lastDayOfMonth().endTimeOfDay().timestamp())
//     .build();
// }

}
